home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / web / spiderweb / tools / excerpt / filesplit.web < prev    next >
Text File  |  1988-03-13  |  4KB  |  164 lines

  1. @*Splitting mailing lists.
  2. The object of the game is to split mailing lists into multiple files.
  3. Usage is
  4. $$\hbox{\tt filesplit prefix numbers}$$
  5. where {\tt prefix} is the prefix of all the output file names, and
  6. {\tt numbers} is a list of line numbers on which pieces of the file begin.
  7. The first line of the file is considered line~1
  8. (for compatibility with {\tt awk(1)}).
  9. The numbers must be sorted in increasing order.
  10. A section consists of material from one number to the next.
  11. The material is printed in a file whose name begins with the {\tt prefix},
  12. and which ends with a unique suffix (e.g. {\tt 00001, 00002, ...}).
  13.  
  14. If a section number is preceded by a minus sign,
  15. the section beginning with that line number gets thrown on the floor
  16. instead of printed.
  17.  
  18. If the prefix is |"-"|, we write all the writable sections to standard
  19. output. 
  20. This makes it posssible to extract just pieces of a file.
  21. @<Print usage message and exit@>=
  22. fprintf(stderr,"Usage:\n");
  23. fprintf(stderr,"\tfilesplit prefix numbers...\n");
  24. exit(1);
  25.  
  26.  
  27. @ @c
  28. #include <stdio.h>
  29. main (argc, argv) 
  30.     int argc;
  31.     char ** argv;
  32. {
  33.     char *prefix;
  34.     @<Variable declarations@>;
  35.  
  36.  
  37.     if (argc--<3) {
  38.         @<Print usage message and exit@>;
  39.         }
  40.  
  41.     prefix = *++argv;
  42.     argc--, argv++;
  43.     @<With |argc=number count| and |argv| pointing to list, process
  44.         standard input into files@>;
  45.     exit(0);
  46. }
  47.  
  48. @ With only one number left in the list, our job is to print from that
  49. line to end of file.
  50. Otherwise, we have two numbers, which we'll call |from_line| and |to_line|.
  51. We'll track the current line with |this_line|, which will be the number of
  52. next line schedule to be written to the output (or thrown on the floor).
  53. We have an implicit initial {\tt -1}, i.e. we don't print the initial
  54. segment of the file.
  55. @<Variable dec...@>=
  56.     int from_line, to_line;
  57.     int this_line; /* the number of the next line scheduled to be 
  58.                 printed */
  59.  
  60. @
  61. @<With |argc=number count| and |argv| pointing to list, process
  62.         standard input into files@>=
  63. multi_output=1;
  64. @<If |prefix=="-"|, make |stdout| the output file and set |multi_output=0|@>;
  65. printing=0;
  66. from_line=0;
  67. this_line=1;
  68. while (argc!=0) {
  69.     @<Read an argument into |to_line|, set |next_printing|, 
  70.         check for order, 
  71.         and advance |argv|@>;
  72.     @<If |printing && multi_output|, 
  73.         choose a name for the output file and open it@>;
  74.     while (this_line != to_line) {
  75.         @<Copy current line to output file 
  76.             (or throw out if not |printing|)
  77.             and advance |this_line|,
  78.             jumping to |finish| on end of file@>;
  79.         }
  80.     @<If |printing && multi_output|, close the output file@>;
  81.     from_line = to_line;
  82.     printing = next_printing;
  83.     }
  84. @<If |printing && multi_output|, 
  85.     choose a name for the output file and open it@>;
  86. while (1) {
  87.     @<Copy current line to output file...@>;
  88.     }
  89. finish:
  90.     @<Yelp if we ended prematurely@>;
  91.  
  92.  
  93. @ We ended prematurely if |from_line!=to_line|.
  94. @<Yelp...@>=
  95. if (from_line != to_line)
  96.     fprintf(stderr,"filesplit: premature end of file\n");
  97.  
  98.  
  99.  
  100.  
  101. @ We might as well get the details of the output files done with now.
  102. @<Variable dec...@>=
  103.     FILE *output;
  104.     char filename[255];
  105.     int sequence_number=0;
  106.     int multi_output;
  107. @ @<If |prefix=="-"|, make |stdout| the output file and set |multi_output=0|@>=
  108. if (!strcmp(prefix,"-")) {
  109.     output=stdout;
  110.     multi_output=0;
  111.     }
  112.  
  113. @ @<If |printing && multi_output|, choose a name...@>=
  114. if (printing && multi_output) {
  115.     sprintf(filename,"%s%05d", prefix, sequence_number++);
  116.     if ((output=fopen(filename,"w"))==NULL) {
  117.         @<Print an error message and exit@>;
  118.         }
  119.     }
  120.  
  121. @ @<If |printing && multi_output|, close the output file@>=
  122. if (printing && multi_output) fclose(output);
  123.  
  124. @ Here's how the copying works
  125. @<Copy current line to output file...@>=
  126. while ((c=getchar())!=EOF) {
  127.     if (printing) putc(c,output);
  128.     if (c=='\n') {
  129.         this_line++;
  130.         break;
  131.         }
  132.     }
  133. if (c==EOF) goto finish;
  134. @ @<Variable dec...@>=char c;
  135.  
  136. @ Since we determine sign when we read the target, we save the sign to set
  137. |printing| the next time around.
  138. @<Variable dec...@>=int printing, next_printing;
  139.  
  140.  
  141.  
  142. @ Here's our argument processing:
  143. @ @<Read an argument into |to_line|...@>=
  144. sscanf(*argv++,"%d",&to_line); argc--;
  145. if (to_line<0) {
  146.     to_line = - to_line;
  147.     next_printing = 0;
  148.     }
  149. else {
  150.     next_printing=1;
  151.     }
  152.  
  153. if (to_line <= from_line) {
  154.     fprintf(stderr,"filesplit: numbers out of order\n");
  155.     exit(-1);
  156.     }
  157.  
  158.  
  159. @ @<Print an error message and exit@>=
  160. fprintf(stderr,"filesplit: I couldn't open a file or something\n");
  161. exit(-1);
  162.  
  163. @*Index.
  164.